//go:build windows
// +build windows

package service

import (
	"fmt"
	"os/exec"
	"strings"

	"gitee.com/liumou_site/gcs"
	"gitee.com/liumou_site/logger"
)

// Service 结构体用于管理服务配置
type Service struct {
	Name     string
	Interval int
	Cmd      gcs.ApiShell
}

// NewServiceWindows 创建新的WindowsService实例
func NewServiceWindows(name string, interval int) *Service {
	return &Service{
		Name:     name,
		Interval: interval,
		Cmd:      *gcs.NewShell(),
	}
}

// Create 创建Windows服务
func (s *Service) Create() error {
	// 优先使用sc命令创建Windows服务
	if err := s.createWithSC(); err == nil {
		return nil
	}

	// 如果sc命令失败，回退到任务计划程序
	logger.Warn("sc命令创建服务失败，尝试使用任务计划程序...")
	return s.createWithTaskScheduler()
}

// createWithSC 使用sc命令创建Windows服务
func (s *Service) createWithSC() error {
	// 检查是否已存在服务
	if s.checkWithSC() {
		logger.Info("Windows服务已存在，跳过创建")
		return nil
	}

	// 确保服务文件在正确位置
	servicePath, err := EnsureServiceFile()
	if err != nil {
		return fmt.Errorf("确保服务文件位置失败: %v", err)
	}

	// 使用sc命令创建服务
	s.Cmd.RunShell("sc", "create", s.Name,
		"binPath=", fmt.Sprintf("\"%s\" -hour %d", servicePath, s.Interval),
		"start=", "auto",
		"DisplayName=", s.Name+" Service",
		"obj=", "LocalSystem")

	if s.Cmd.Err != nil {
		return fmt.Errorf("创建Windows服务失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
	}

	// 启动服务
	s.Cmd.RunShell("sc", "start", s.Name)
	if s.Cmd.Err != nil {
		logger.Warn("启动服务失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
		// 不返回错误，因为服务已创建成功
	}

	logger.Info("Windows服务已创建并设置为自动启动")
	logger.Info("服务名称: %s", s.Name)
	logger.Info("启动类型: 自动")
	logger.Info("服务文件路径: %s", servicePath)

	return nil
}

// createWithNSSM 使用NSSM创建Windows服务（备用方案）
func (s *Service) createWithNSSM() error {
	// 确保服务文件在正确位置
	servicePath, err := EnsureServiceFile()
	if err != nil {
		return fmt.Errorf("确保服务文件位置失败: %v", err)
	}

	// 检查NSSM是否存在
	if _, err = exec.LookPath("nssm"); err != nil {
		return fmt.Errorf("NSSM未安装，请先安装NSSM")
	}

	// 使用NSSM创建服务
	s.Cmd.RunShell("nssm", "install", s.Name, servicePath, fmt.Sprintf("-h %d", s.Interval))
	if s.Cmd.Err != nil {
		return fmt.Errorf("NSSM创建服务失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
	}

	// 设置服务为自动启动
	s.Cmd.RunShell("nssm", "set", s.Name, "Start", "SERVICE_AUTO_START")

	// 启动服务
	s.Cmd.RunShell("net", "start", s.Name)

	logger.Info("NSSM Windows服务已创建: %s", s.Name)
	return nil
}

// createWithTaskScheduler 使用schtasks创建Windows任务计划
func (s *Service) createWithTaskScheduler() error {
	// 确保服务文件在正确位置
	servicePath, err := EnsureServiceFile()
	if err != nil {
		return fmt.Errorf("确保服务文件位置失败: %v", err)
	}

	// 创建任务命令
	s.Cmd.RunShell("schtasks", "/create", "/tn", s.Name, "/tr",
		fmt.Sprintf("\"%s\" -hour %d", servicePath, s.Interval),
		"/sc", "HOURLY", "/mo", fmt.Sprintf("%d", s.Interval), "/ru", "SYSTEM")

	if s.Cmd.Err != nil {
		if strings.Contains(s.Cmd.Strings, "already exists") {
			logger.Info("任务计划已存在，跳过创建")
			return nil
		}
		return fmt.Errorf("创建任务计划失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
	}

	logger.Info("Windows任务计划已创建")
	logger.Info("任务名称: %s", s.Name)
	logger.Info("执行间隔: 每%d小时", s.Interval)

	return nil
}

// RemoveTaskScheduler 移除Windows任务计划
func (s *Service) RemoveTaskScheduler() error {
	s.Cmd.RunShell("schtasks", "/delete", "/tn", s.Name, "/f")

	if s.Cmd.Err != nil {
		if strings.Contains(s.Cmd.Strings, "does not exist") {
			logger.Info("任务计划不存在，跳过删除")
			return nil
		}
		return fmt.Errorf("删除任务计划失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
	}

	logger.Info("Windows任务计划已删除: %s", s.Name)
	return nil
}

// Exists 检查Windows服务状态（兼容任务计划和服务）
func (s *Service) Exists() bool {
	// 优先检查Windows服务
	if s.checkWithSC() {
		return true
	}

	// 检查任务计划作为备选
	return s.checkWithTaskScheduler()
}

// checkWithSC 检查Windows服务状态（使用sc命令）
func (s *Service) checkWithSC() bool {
	s.Cmd.RunShell("sc", "query", s.Name)

	if s.Cmd.Err != nil {
		return false
	}

	if strings.Contains(s.Cmd.Strings, "STATE") {
		logger.Info("Windows服务已存在: %s", s.Name)
		return true
	}

	return false
}

// checkWithTaskScheduler 检查Windows任务计划是否存在
func (s *Service) checkWithTaskScheduler() bool {
	s.Cmd.RunShell("schtasks", "/query", "/tn", s.Name)
	if s.Cmd.Err == nil && strings.Contains(s.Cmd.Strings, s.Name) {
		logger.Info("Windows任务计划已存在: %s", s.Name)
		return true
	}
	return false
}

// Remove 移除Windows服务
func (s *Service) Remove() error {
	logger.Info("开始移除Windows服务: %s", s.Name)

	// 检查服务是否存在
	if !s.Exists() {
		logger.Info("服务不存在，跳过移除: %s", s.Name)
		return nil
	}

	// 停止服务
	s.Cmd.RunShell("sc", "stop", s.Name)

	// 删除服务
	s.Cmd.RunShell("sc", "delete", s.Name)
	if s.Cmd.Err != nil {
		if strings.Contains(s.Cmd.Strings, "does not exist") {
			// 服务不存在，尝试移除任务计划
			return s.RemoveTaskScheduler()
		}
		return fmt.Errorf("删除Windows服务失败: %v, 输出: %s", s.Cmd.Err, s.Cmd.Strings)
	}

	// 清理服务文件
	if err := RemoveServiceFile(); err != nil {
		logger.Warn("清理服务文件失败: %v", err)
	} else {
		logger.Info("已清理服务文件")
	}

	logger.Info("Windows服务已移除: %s", s.Name)
	return nil
}
